/******************************************************************************
BigWorld Technology
Copyright BigWorld Pty, Ltd.
All Rights Reserved. Commercial in confidence.

WARNING: This computer program is protected by copyright law and international
treaties. Unauthorized use, reproduction or distribution of this program, or
any portion of this program, may result in the imposition of civil and
criminal penalties as provided by law.
******************************************************************************/

/* stdmf.hpp: library wide definitions
 */
#ifndef STDMF_HPP
#define STDMF_HPP

#ifndef _WIN32
#include <unistd.h>
#include <sys/types.h>
#else
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

#include <limits>
#include <math.h>

/* --------------------------------------------------------------------------
 * Constants
 * --------------------------------------------------------------------------
 */

//#define NT_ENABLED

#ifdef __WATCOMC__
#ifndef false
#define false		0
#define true		1
#endif
#endif // __WATCOMC__

/*
#define ASCII_NUL	0x00
#define ASCII_SOH	0x01
#define ASCII_STX	0x02
#define ASCII_ETX	0x03
#define ASCII_EOT	0x04
#define ASCII_ENQ	0x05
#define ASCII_ACK	0x06
#define ASCII_BEL	0x07
#define ASCII_BS	0x08
#define ASCII_HT	0x09
#define ASCII_LF	0x0a
#define ASCII_VT	0x0b
#define ASCII_FF	0x0c
#define ASCII_CR	0x0d
#define ASCII_SO	0x0e
#define ASCII_SI	0x0f
#define ASCII_DLE	0x10
#define ASCII_DC1	0x11
#define ASCII_DC2	0x12
#define ASCII_DC3	0x13
#define ASCII_DC4	0x14
#define ASCII_NAK	0x15
#define ASCII_SYN	0x16
#define ASCII_ETB	0x17
#define ASCII_CAN	0x18
#define ASCII_EM	0x19
#define ASCII_SUB	0x1a
#define ASCII_ESC	0x1b
#define ASCII_FS	0x1c
#define ASCII_GS	0x1d
#define ASCII_RS	0x1e
#define ASCII_US	0x1f
*/



/* --------------------------------------------------------------------------
 * Types
 * --------------------------------------------------------------------------
 */

/// This type is an unsigned character.
typedef unsigned char	uchar;
/// This type is an unsigned short.
typedef unsigned short	ushort;
/// This type is an unsigned integer.
typedef unsigned int	uint;
/// This type is an unsigned longer.
typedef unsigned long	ulong;

/// This type is an integer with a size of 8 bits.
typedef char			int8;
/// This type is an integer with a size of 16 bits.
typedef short			int16;
/// This type is an integer with a size of 32 bits.
typedef long			int32;
#define DEF_INT32
/// This type is an unsigned integer with a size of 8 bits.
typedef unsigned char	uint8;
/// This type is an unsigned integer with a size of 16 bits.
typedef unsigned short	uint16;
/// This type is an unsigned integer with a size of 32 bits.
typedef unsigned long	uint32;
#define DEF_UINT32

#ifdef _WIN32
typedef __int64				int64;
typedef unsigned __int64	uint64;
#else // unix
/// This type is an integer with a size of 64 bits.
typedef long long			int64;
/// This type is an unsigned integer with a size of 64 bits.
typedef unsigned long long	uint64;
#endif

#if defined(_WIN32) && !defined(_XBOX)
// This type is an integer with the size of a pointer.
typedef INT_PTR				intptr;
// This type is an unsigned integer with the size of a pointer.
typedef UINT_PTR        	uintptr;
#else
typedef int32				intptr;
typedef uint32				uintptr;
#endif

/// This type is used for a 4 byte file header descriptor.
//typedef uint32			HdrID;		/* 4 byte (file) descriptor */
/// This type is used for a generic 4 byte descriptor.
//typedef uint32			ID;			/* 4 byte generic descriptor */


/* --------------------------------------------------------------------------
 * Macros
 * --------------------------------------------------------------------------
 */



/* array & structure macros
 */
#if 0
#define ARRAYCLR(v)					memset((v), 0x0, sizeof(v))
#define MEMCLR(v)					memset(&(v), 0x0, sizeof(v))
#define MEMCLRP(v)					memset((v), 0x0, sizeof(*v))
#endif

#define ARRAYSZ(v)					(sizeof(v) / sizeof(v[0]))
#define ARRAY_SIZE(v)				(sizeof(v) / sizeof(v[0]))

#if 0
#define offsetof(type, field)		((uint32)&(((type *)NULL)->field))
#ifndef FIELD_OFFSET
#define FIELD_OFFSET(type, field)	offsetof(type, field)
#endif
#ifndef FIELD_SIZE
#define FIELD_SIZE(type, field)		(sizeof(((type *)NULL)->field))
#endif
#endif

/* string comparing
 */
/// Returns true if two strings are equal.
#define STR_EQ(s, t)		(!strcmp((s), (t)))
/// Returns true if two strings are the same, ignoring case.
#define STR_EQI(s, t)		(!bw_stricmp((s), (t)))
/// Returns true if the first sz byte of the input string are equal, ignoring
/// case.
#define STRN_EQI(s, t, sz)	(!bw_strnicmp((s), (t), (sz)))
/// Returns true if the first sz byte of the input string are equal, ignoring
/// case.
#define STRN_EQ(s, t, sz)	(!strncmp((s), (t), (sz)))
/// Returns true if all three input string are equal.
#define STR_EQ2(s, t1, t2)	(!(strcmp((s), (t1)) || strcmp((s), (t2))))


/* scalar types comparing
 */

#include <algorithm>

#if defined(_WIN32)

#undef min
#define min min
#undef max
#define max max

template <class T>
inline const T & min( const T & a, const T & b )
{
	return b < a ? b : a;
}

template <class T>
inline const T & max( const T & a, const T & b )
{
	return a < b ? b : a;
}

#define MF_MIN min
#define MF_MAX max

#define NOMINMAX

#else

#define MF_MIN std::min
#define MF_MAX std::max

#endif


/**
 * This macro creates a long out of 4 chars, used for all id's: ID, HdrId.
 * @note byte ordering on 80?86 == 4321
 */
#if 0
#define MAKE_ID(a, b, c, d)	\
	(uint32)(((uint32)(d)<<24) | ((uint32)(c)<<16) | ((uint32)(b)<<8) | (uint32)(a))
#endif


/* Intel Architecture is little endian (low byte presented first)
 * Motorola Architecture is big endian (high byte first)
 */
/// The current architecture is Little Endian.
#define MF_LITTLE_ENDIAN
/*#define MF_BIG_ENDIAN*/

#ifdef MF_LITTLE_ENDIAN
/* accessing individual bytes (int8) and words (int16) within
 * words and long words (int32).
 * Macros ending with W deal with words, L macros deal with longs
 */
/// Returns the high byte of a word.
#define HIBYTEW(b)		(((b) & 0xff00) >> 8)
/// Returns the low byte of a word.
#define LOBYTEW(b)		( (b) & 0xff)

/// Returns the high byte of a long.
#define HIBYTEL(b)		(((b) & 0xff000000L) >> 24)
/// Returns the low byte of a long.
#define LOBYTEL(b)		( (b) & 0xffL)

/// Returns byte 0 of a long.
#define BYTE0L(b)		( (b) & 0xffL)
/// Returns byte 1 of a long.
#define BYTE1L(b)		(((b) & 0xff00L) >> 8)
/// Returns byte 2 of a long.
#define BYTE2L(b)		(((b) & 0xff0000L) >> 16)
/// Returns byte 3 of a long.
#define BYTE3L(b)		(((b) & 0xff000000L) >> 24)

/// Returns the high word of a long.
#define HIWORDL(b)		(((b) & 0xffff0000L) >> 16)
/// Returns the low word of a long.
#define LOWORDL(b)		( (b) & 0xffffL)

/**
 *	This macro takes a dword ordered 0123 and reorder it to 3210.
 */
#define SWAP_DW(a)	  ( (((a) & 0xff000000)>>24) |	\
						(((a) & 0xff0000)>>8) |		\
						(((a) & 0xff00)<<8) |		\
						(((a) & 0xff)<<24) )

#else
/* big endian macros go here */
#endif

/// This macro is used to enter the debugger.
#ifdef _WIN32
#define ENTER_DEBUGGER() __asm { int 3 }
#else
#define ENTER_DEBUGGER() asm( "int $3" )
#endif


void initBackEndProcess( int uid, int pid );
extern int g_backEndUID;
extern int g_backEndPID;
extern bool g_isBackEndProcess;

void initBackEndProcess( int uid, int pid );


/**
 *	This function returns user id.
 */
inline int getUserId()
{
	if (g_isBackEndProcess)
		return g_backEndUID;

	char * uid = getenv( "UID" );

#ifdef _WIN32
	return uid ? atoi( uid ) : 0;
#else
	return uid ? atoi( uid ) : getuid();
#endif
}


/**
 *	This function returns the process id.
 */
inline int mf_getpid()
{
	if (g_isBackEndProcess)
		return g_backEndPID;

#if defined(unix)
	return getpid();
#else
	return (int) GetCurrentProcessId();
#endif
}

#if defined( unix )

#define bw_isnan isnan
#define bw_isinf isinf
#define bw_snprintf snprintf
#define bw_vsnprintf vsnprintf
#define bw_snwprintf snwprintf
#define bw_stricmp strcasecmp
#define bw_strnicmp strncasecmp
#define bw_fileno fileno

#else

#define bw_isnan _isnan
#define bw_isinf(x) (!_finite(x) && !_isnan(x))
#define bw_snprintf _snprintf
#define bw_vsnprintf _vsnprintf
#define bw_snwprintf _snwprintf
#define bw_stricmp _stricmp
#define bw_strnicmp _strnicmp
#define bw_fileno _fileno

#endif // unix

/* --------------------------------------------------------------------------
 * STL type info
 * --------------------------------------------------------------------------
 */

template <class MAP> struct MapTypes
{
#ifdef _WIN32
#if _MSC_VER>=1300 // VC7
	typedef typename MAP::mapped_type & _Tref;
#else
	typedef typename MAP::_Tref _Tref;
#endif
#else
	typedef typename MAP::mapped_type & _Tref;
#endif
};


#define MF_FLOAT_EQUAL(value1, value2) \
	(abs(value1 - value2) < std::numeric_limits<float>::epsilon())

// use 0.0004 because most existing functions are using it
inline bool almostEqual( const float f1, const float f2, const float epsilon = 0.0004f )
{
	return fabsf( f1 - f2 ) < epsilon;
}

inline bool almostEqual( const double d1, const double d2, const double epsilon = 0.0004 )
{
	return fabs( d1 - d2 ) < epsilon;
}

inline bool almostZero( const float f, const float epsilon = 0.0004f )
{
	return almostEqual( f, 0.f, epsilon );
}

inline bool almostZero( const double d, const double epsilon = 0.0004f )
{
	return almostEqual( d, 0., epsilon );
}

template<typename T>
inline bool almostEqual( const T& c1, const T& c2, const float epsilon = 0.0004f )
{
	if( c1.size() != c2.size() )
		return false;
	typename T::const_iterator iter1 = c1.begin();
	typename T::const_iterator iter2 = c2.begin();
	for( ; iter1 != c1.end(); ++iter1, ++iter2 )
		if( !almostEqual( *iter1, *iter2, epsilon ) )
			return false;
	return true;
}

#endif // STDMF_HPP

/*end:stdmf.hpp*/
